import { Scene } from '@babylonjs/core/scene';
import { AbstractGroup, IAbstractGroupOptions } from './abstract-group';
import { IUISelectGridOptions, UISelectGrid } from './ui-select-grid';
import { IHandle } from '../../data/data-handle';
import { Utils } from '../../tool/utils';


/**
 * 选择框组控件参数对象
 * @param selectedValue 选中项集合
 * @param revocable 是否可撤销
 * @param multipleSelection 是否可多选
 */
interface IUISelectGridGroupOptions extends IAbstractGroupOptions<IUISelectGridOptions> {
    selectedValue?: string[],
    revocable?: boolean,
    multipleSelection?: boolean,
}


/**
 * 选择框组控件
 * @param name 名称
 * @param scene 所在场景
 * @param options 参数对象
 */
class UISelectGridGroup extends AbstractGroup {

    private _selectedValue: string[] = [];
    private _revokable!: boolean;
    private _multipleSelection!: boolean;

    constructor(name: string, scene: Scene, options?: IUISelectGridGroupOptions) {
        super(name, scene, options);
        const ops = options || {};
        let vs = ops.selectedValue || [];
        if ((!this._multipleSelection) && (vs.length > 1)) vs = [vs[0]];
        this.selectedValue = vs;
    }

    /**
     * 设置选中项
     */
    public set selectedValue(values: string[]) {
        const vs = Utils.noDuplication(values);
        for (const item of this.items) {
            (item as UISelectGrid).isSelected = vs.includes(item.key);
        }
    }

    /**
     * 获取选中项
     */
    public get selectedValue(): string[] {
        return [...this._selectedValue];
    }

    public onChange(func: { (values: string[]): void }): IHandle<string[]> {
        return super.onChange(func);
    }

    protected generateItem(name: string, scene: Scene, itemOptions: IUISelectGridOptions, groupOptions: IUISelectGridGroupOptions): UISelectGrid {
        if (!this._selectedValue) {
            this._revokable = groupOptions.revocable === undefined ? true : groupOptions.revocable;
            this._multipleSelection = !!groupOptions.multipleSelection;
        }

        const grid = new UISelectGrid(name, scene, itemOptions);

        grid.onChange((isSelected: boolean) => {
            const values = this._selectedValue;
            const oValues = [...this._selectedValue];
            const key = grid.key;
            const sn = isSelected;
            const rn = this._revokable;
            const mn = this._multipleSelection;
            if (sn && mn) {
                if (!values.includes(key)) values.push(key);
            } else if (sn && (!mn)) {
                values.length = 0;
                values.push(key);
            } else if ((!sn) && rn) {
                const idx = values.indexOf(key);
                if (idx >= 0) values.splice(idx, 1);
            }
            for (const item of this.items) {
                (item as UISelectGrid).isSelected = values.includes(item.key);
            }

            let change = false;
            if (values.length !== oValues.length) {
                change = true;
            } else {
                for (const v of values) {
                    if (oValues.includes(v)) continue;
                    change = true;
                    break;
                }
            }
            if (change) {
                if (!this.avoidEventHandle) this.changeHandles.forEach(handle => handle.callback([...values]));
            }
        });

        return grid;
    }

}


/**
 * 创建选择框组控件
 * @param name 名称
 * @param scene 所在场景
 * @param options 参数对象
 * @param changeCallback 选项改变时的回调函数
 * @returns 选择框组控件
 */
const CreateUISelectGridGroup = (name: string, scene: Scene, options?: IUISelectGridGroupOptions, changeCallback?: { (values: string[]): void }): UISelectGridGroup => {
    const group = new UISelectGridGroup(name, scene, options);
    if (changeCallback) group.onChange(changeCallback);
    return group;
};


export { UISelectGridGroup, CreateUISelectGridGroup };
export type { IUISelectGridGroupOptions };